<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 * @author   howe <howe1995@163.com>
 */

namespace App\Services;

use App\Constant\ApiCodeEnum;
use App\Constant\Database\FriendEnum;
use App\Constant\Database\MomentEnum;
use App\Constant\Database\UserEnum;
use App\Exception\BusinessException;
use App\Helper\HashHelper;
use App\Model\Friend;
use App\Model\User;
use App\Repository\MomentRepository;
use App\Support\Traits\ServiceException;
use Exception;
use Hyperf\DbConnection\Db;
use Hyperf\Stringable\Str;

use function Hyperf\Config\config;

class UserService
{
    use ServiceException;

    /**
     * 登录逻辑.
     *
     * @param string $mobile 手机号
     * @param string $password 登录密码
     * @return array
     * @throws BusinessException
     */
    public function login(string $mobile, string $password, bool $auto = false)
    {
        $user = User::query()->where('mobile', $mobile)->first();
        if (! $user) {
            $this->throwBusinessException(ApiCodeEnum::SERVICE_ACCOUNT_NOT_FOUND);
        }
        if ($user->status != UserEnum::STATUS_NORMAL) {
            $this->throwBusinessException(ApiCodeEnum::SERVICE_ACCOUNT_DISABLED);
        }
        if (! $auto) {
            // 密码验证
            if (! HashHelper::check($user->salt . $password, $user->password)) {
                $this->throwBusinessException(ApiCodeEnum::SERVICE_ACCOUNT_OR_PASSWORD_ERROR);
            }
        }

        $token = auth()->guard()->login($user);
        $tokenTtl = auth()->guard()->getJwtManager()->getTtl();
        $user->token = $token;
        $user->token_expire_in = time() + $tokenTtl;
        $user->save();
        $user = $user->toArray();
        unset($user['password'], $user['salt']);
        return $user;
    }

    /**
     * 账号注册逻辑.
     *
     * @return array|void
     * @throws BusinessException
     */
    public function register(array $params)
    {
        Db::beginTransaction();
        try {
            $user = User::query()->where('mobile', $params['mobile'])->orWhere('wechat', $params['wechat'])->first(['mobile', 'wechat']);
            if ($user && $user->mobile == $params['mobile']) {
                $this->throwBusinessException(ApiCodeEnum::SERVICE_ACCOUNT_ALREADY_EXISTS);
            }
            if ($user && $user->wechat == $params['wechat']) {
                $this->throwBusinessException(ApiCodeEnum::SERVICE_WECHAT_ALREADY_EXISTS);
            }
            $params['salt'] = Str::password(10);
            $params['setting'] = config('user.owner.setting');
            $params['unread'] = config('user.owner.unread');
            $params['password'] = HashHelper::make($params['salt'] . $params['password']);
            if (empty($params['avatar'])) {
                $params['avatar'] = rand_avatar($params['mobile']);
            }
            $user = User::create($params);
            // 把ai小助手添加为朋友
            (new AssistantService())->becomeFriendWhenRegister($user->toArray());

            Db::commit();
            // 自动登录
            return $this->login($params['mobile'], $params['password'], true);
        } catch (Exception $e) {
            logInfo('register_error', $e->getMessage());
            Db::rollBack();
            $this->throwBusinessException(ApiCodeEnum::FAILED_DEFAULT);
        }
    }

    /**
     * 账号重置密码
     *
     * @param string $mobile 用户手机号
     * @param string $password 新密码
     */
    public function resetPassword(string $mobile, string $password): bool
    {
        $data = User::query()->where('mobile', $mobile)->first();
        if (! $data) {
            return false;
        }
        $data->password = HashHelper::make($data->salt . $password);
        return $data->save();
        // return (bool)$this->userRepository->update(["mobile" => $mobile], [
        //     'password' => HashHelper::make($password)
        // ]);
    }

    /**
     * 主页.
     */
    public function home(array $params): array
    {
        $isMobile = is_mobile($params['keywords']);
        $field = $isMobile ? 'mobile' : 'wechat';
        $user = User::query()->where($field, $params['keywords'])->first(['id', 'nickname', 'wechat', 'avatar', 'gender', 'sign', 'moment_bg_file_path']);

        if (! $user) {
            $this->throwBusinessException(ApiCodeEnum::CLIENT_DATA_NOT_FOUND);
        }
        $params['user_id'] = $user->id;
        $userId = $params['user']->id;
        $self = $user->id == $userId;
        $relationship = 'owner';
        $source = $isMobile ? 'mobile' : 'wechat';
        $setting = config('user.friend.setting');
        $homeInfo = ['moment' => [], 'relationship' => 'owner', 'source' => $source, 'source_text' => '', 'remark' => '', 'keywords' => $params['keywords'], 'display_nickname' => $user->nickname];
        $homeInfo = array_merge($homeInfo, $user->toArray());
        $sourceConfig = config('user.source');
        $assistantIds = get_assistant_ids();
        if (! $self) {
            $relationship = FriendEnum::TYPE_APPLY;
            $owner = Friend::query()->where('owner', $userId)->where('friend', $user->id)->first();
            $friend = Friend::query()->where('owner', $user->id)->where('friend', $userId)->first();
            $homeInfo['source_text'] = '通过' . $sourceConfig[$source] . '搜索';
            $homeInfo['check_msg'] = '';
            if ($friend && $friend->status == FriendEnum::STATUS_CHECK) {
                $relationship = FriendEnum::RELATIONSHIP_GO_CHECK;
                $homeInfo['source_text'] = '对方通过' . $sourceConfig[$friend->source] . '搜索';
                $homeInfo['remark'] = $friend->remark;
                $homeInfo['check_msg'] = "{$user->nickname}：{$friend->remark}";
            }
            if ($owner && $owner->status == FriendEnum::STATUS_PASS) {
                $relationship = FriendEnum::RELATIONSHIP_FRIEND;
                if (in_array($owner->friend, $assistantIds)) {
                    $homeInfo['source_text'] = '对方是你的AI小助手';
                } else {
                    $prefix = $friend->created_at > $owner->created_at ? '' : '对方';
                    $homeInfo['source_text'] = $prefix . '通过搜索' . $sourceConfig[$owner->source] . '添加';
                }
            }
            if ($owner && $owner->status == FriendEnum::STATUS_CHECK) {
                $relationship = FriendEnum::RELATIONSHIP_WAIT_CHECK;
                $homeInfo['remark'] = $owner->remark;
                $homeInfo['source_text'] = '通过' . $sourceConfig[$owner->source] . '搜索';
                $homeInfo['check_msg'] = "我：{$owner->remark}";
            }
            if ($owner) {
                $homeInfo['display_nickname'] = $owner->nickname ?: $user->nickname;
                $homeInfo['source'] = $owner->source;
                $setting = $owner->setting;
            }
        }
        $homeInfo['relationship'] = $relationship;
        $homeInfo['setting'] = $setting;
        [$pageInfo, $moments] = MomentRepository::getMomentsPageByUserId($params);
        foreach ($moments as $moment) {
            if (in_array($moment['type'], [MomentEnum::IMAGE, MomentEnum::VIDEO]) && ! empty($moment['files'][0]['file']['thumbnail_path']) && count($homeInfo['moment']) < 4) {
                $homeInfo['moment'][] = $moment['files'][0]['file']['thumbnail_path'];
            }
        }
        return $homeInfo;
    }

    /**
     * 用户信息.
     */
    public function info(array $params): array
    {
        $id = $params['id'];
        $userId = $params['user']->id;
        $self = $id == $userId;
        $user = User::query()->find($params['id'], ['id', 'nickname', 'avatar', 'wechat', 'mobile', 'gender', 'sign', 'setting'])->toArray();
        $user['keywords'] = $user['wechat'];
        if (! $self) {
            $owner = Friend::query()->where('owner', $userId)->where('friend', $id)->first(['nickname', 'setting', 'source']);
            if ($owner) {
                $user['setting'] = $owner->setting;
                $user['nickname'] = $owner->nickname ?: $user['nickname'];
                $user['keywords'] = $user[$owner->source];
                $user['desc'] = $owner->desc;
            }
        }
        unset($user['mobile']);
        return $user;
    }

    public function update(array $params): array
    {
        $userId = $params['user']->id;
        $updateAllowFields = ['avatar', 'gender', 'sign', 'nickname', 'setting', 'bg_file_id', 'bg_file_path', 'moment_bg_file_id', 'moment_bg_file_path'];
        $updateData = [];
        foreach ($params as $key => $value) {
            if (in_array($key, $updateAllowFields)) {
                $updateData[$key] = is_array($value) ? json_encode($value) : $value;
            }
        }
        if ($updateData) {
            User::query()->where('id', $userId)->update($updateData);
        }
        return $updateData;
    }

    /**
     * 用户个人朋友圈.
     */
    public function moments(array $params): array
    {
        [$pageInfo, $moments] = MomentRepository::getMomentsPageByUserId($params);
        $list = [];
        foreach ($moments as $moment) {
            $moment['created_at'] = strtotime($moment['created_at']);
            $year = date('Y', $moment['created_at']);
            $date = date('Ymd', $moment['created_at']);
            $list[$year]['year'] = $year;
            $list[$year]['current_year'] = date('Y');
            if (isset($list[$year]['moments'][$date])) {
                $list[$year]['moments'][$date]['list'][] = $moment;
            } else {
                $list[$year]['moments'][$date]['ts'] = $moment['created_at'];
                $list[$year]['moments'][$date]['list'] = [$moment];
            }
        }
        unset($moments);
        foreach ($list as &$item) {
            $item['moments'] = array_values($item['moments']);
        }
        return [$pageInfo, array_values($list)];
    }
}
